home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / cylinder2.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  18KB  |  665 lines

  1. /*
  2.  * Copyright (c) 1993-94, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  21.  */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <math.h>
  25. #include <GL/gl.h>
  26. #include <GL/glu.h>
  27. #include <GL/glx.h>
  28. #include <X11/Xlib.h>
  29. #include <X11/Xutil.h>
  30. #include <X11/keysym.h>
  31.  
  32. /*
  33.  * we'll define our own PI, could get it
  34.  * from math.h, but i'm not in the mood
  35.  */
  36. #define M_PI            3.14159265358979323846
  37.  
  38. /*
  39.  * some local functions
  40.  */
  41. void drawScene(void);
  42. void drawcyl(void);
  43. void drawBox(void);
  44. void setMaterial(GLenum, float *, float *, float *, float *);
  45.  
  46. /*
  47.  * define some lighting properties
  48.  */
  49. static float ambient[] = { 0.2, 0.2, 0.2, 1.0 };
  50. static float diffuse[] = { 0.6, 0.6, 0.6, 1.0 };
  51. static float specular[] = { 1.0, 1.0, 1.0, 1.0 };
  52. static float alm[] = { 0.1, 0.1, 0.1, 1};
  53. static float lpos[] = { 0, 0, 100, 0 };
  54. static float shininess[] = { 128.0 };
  55.  
  56. /*
  57.  * define material properties.  
  58.  */
  59. static float ambient2[] = { 0.4, 0.0, 0.4, 1.0 };
  60. static float diffuse2[] = { 0.7, 0.0, 0.7, 1.0 };
  61. static float specular2[] = { 1.0, 1.0, 1.0, 1.0 };
  62.  
  63. float bamat[] = {.4, .4, .4, 1.0};
  64. float bdmat[] = { 0.8, .8, .8, 1.0};
  65. float bsmat[] = { .1, .1, .1, 1.0};
  66.  
  67. float amat[] = {.1, .1, .2, 0.3};
  68. float dmat[] = { 0.3, .3, .5, 0.3};
  69. float smat[] = { 1.0, 1.0, 1.0, 0.3};
  70. float shin[] = { 128.0 };
  71.  
  72. float amat2[] = {.1, .1, .1, 0.5};
  73. float dmat2[] = { .3690, .0, .165, 0.5};
  74. float smat2[] = { .8, .8, .8, 0.5};
  75.  
  76.  
  77. /*
  78.  * the attribute list for the OpenGL visual.
  79.  * we only request 1 bit for each color and depth, we get more
  80.  * than 1 bit for each, i just put in for the minimum, the
  81.  * server should return a visual that meets these requirements or
  82.  * better...
  83.  */
  84. static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, 
  85.     GLX_RED_SIZE, 1,
  86.     GLX_GREEN_SIZE, 1,
  87.     GLX_BLUE_SIZE, 1,
  88.     GLX_DEPTH_SIZE, 1,
  89.     None };
  90.  
  91. /*
  92.  * the attribute list for the overlay OpenGL visual.
  93.  * notice that we define 2 of them, GLX_LEVEL 2 and 1.
  94.  * we will try to get an overlay visual (GLX_LEVEL 2).  if we can't get one,
  95.  * we will try to overlay planes (GLX_LEVEL 1)
  96.  */
  97. static int al2[] = {GLX_LEVEL, 2,  None };
  98.  
  99. static int al3[] = {GLX_LEVEL, 1,  None };
  100.  
  101. /*
  102.  * a convenience function, just waits for the window to map.  this
  103.  * is handy, since we don't want to risk OpenGL drawing into an
  104.  * unmapped window, that would be bad...
  105.  */
  106. static Bool WaitForNotify (Display *d, XEvent *e, char *arg)
  107. {
  108.     return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
  109. }
  110.  
  111. /*
  112.  * default window size...
  113.  */
  114. #define WINSIZE 600
  115.  
  116. /*
  117.  * a few global variables
  118.  */
  119. int WIRE_FRAME = 0;
  120. int TRANSPARENT = 0;
  121. int RESET = True;
  122. int WHITE_PIXEL_NUM;
  123.  
  124. int  xorigin, yorigin;        /* window x and y locations */
  125. unsigned int  width, height;  /* window width and height  */
  126. float rx, ry;                 /* adjusted x and y locations */
  127. Display *dpy;                 /* X Display */
  128. Window win;                   /* OpenGL X Window ID */
  129. Window owin;                  /* OpenGL overlay X Window ID */ 
  130. GLXContext cx;                /* context for the OpenGL window */
  131. GLXContext ocx;               /* context for the overlay OpenGL window */
  132.  
  133. Window winList[3];            /* X window ID list, needed to map window 
  134.                   colormaps */
  135.  
  136.  
  137. /*
  138.  * main routine.  
  139.  */
  140. main()
  141. {
  142.  
  143.     XVisualInfo *vi;              /* X Visual  */
  144.     Colormap cmap, ocmap;         /* X Colormap */
  145.     XSetWindowAttributes swa;     /* X Window Attributes */
  146.     XEvent event;                 /* X event             */
  147.     char    xbuf[20];             /* character buffer */
  148.     int     nchar = 20;           /* size of character buffer */
  149.     KeySym  key;                  /* keyboard key hit */
  150.     XComposeStatus cs;            /* X keyboard compose structure */
  151.     XWindowAttributes winattrs;   /* X Window attribute structure */
  152.     XColor  spix, pixel;          /* X pixel structure */
  153.     float fx, fy;                 /* adjusted x & y cursor positions */
  154.  
  155.  
  156.   /*
  157.    * open a connection to the local display
  158.    */
  159.     dpy = XOpenDisplay (0);
  160.  
  161.   /* 
  162.    * get an OpenGL main plane visual, if we fail, big problems, 
  163.    * exit... 
  164.    */
  165.     if (!(vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList))) {
  166.         printf("\n can't get requested visual type, bye...\n");
  167.         exit(0);
  168.         }
  169.  
  170.   /* create a GLX context */
  171.     cx = (GLXContext) glXCreateContext (dpy, vi, None, GL_TRUE);
  172.  
  173.   /* create a colormap using this visual */
  174.     cmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
  175.                             AllocNone);
  176.  
  177.   /* set up the window attributes and create an X Window */
  178.     swa.colormap = cmap;
  179.     swa.border_pixel = 1;
  180.     swa.event_mask = StructureNotifyMask;
  181.     win = XCreateWindow (dpy, RootWindow(dpy,vi->screen), 
  182.                          0, 0, WINSIZE, WINSIZE,
  183.                          0, vi->depth, InputOutput, vi->visual,
  184.                          CWBorderPixel|CWColormap|CWEventMask, &swa);
  185.  
  186.     XMapWindow (dpy,win);
  187.  
  188.   /* 
  189.    * try to create an overlay window.  first try for GLX_LEVEL 2, a visual
  190.    * in the overlay planes.  if that fails, go for GLX_LEVEL 1, a visual in
  191.    * the popup planes.  if that fails, game over...
  192.    */
  193.  
  194.     if (!(vi = glXChooseVisual (dpy, DefaultScreen(dpy), al2))) {
  195.        
  196.        /*
  197.         * overlay failed, try popup
  198.         */
  199.         fprintf(stderr, "bummer, can't get overlay visual, trying popup...\n"); 
  200.  
  201.         if (!(vi = glXChooseVisual (dpy, DefaultScreen(dpy), al3))) {
  202.            /*
  203.             * popup failed too, bummer 
  204.             */
  205.             fprintf(stderr,
  206.                    "bummer, can't get requested popup visual either, bye...\n");
  207.             exit(0);
  208.             }
  209.         else {  /* got popup visual! */
  210.             fprintf(stderr,"got popup visual!\n");
  211.             }
  212.         }
  213.     else {
  214.         fprintf(stderr, "got overlay visual!\n"); 
  215.          }
  216.  
  217.    /* 
  218.     * create a GLX context for the overlay window
  219.     */
  220.     ocx = (GLXContext) glXCreateContext (dpy, vi, None, GL_TRUE);
  221.  
  222.    /* 
  223.     * create a colormap using this visual
  224.     */
  225.     ocmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
  226.                             AllocNone);
  227.  
  228.    /* 
  229.     * set up window attributes and create a X Window with overlay visual
  230.     */
  231.     swa.colormap = ocmap;
  232.     swa.border_pixel = 0;
  233.     swa.win_gravity = UnmapGravity;
  234.     swa.bit_gravity = NorthWestGravity;
  235.     swa.background_pixel = BlackPixel(dpy, vi->screen);
  236.  
  237.     owin = XCreateWindow (dpy, win, 0, 0, WINSIZE, WINSIZE,
  238.                          0, vi->depth, InputOutput, vi->visual,
  239.                          CWBorderPixel|CWColormap|CWEventMask, &swa);
  240.  
  241.    /*
  242.     * map window
  243.     */
  244.     XMapWindow (dpy,owin);
  245.  
  246.  
  247.    /*
  248.     * wait for main planes window to map so that we can start drawing into
  249.     * it.
  250.     */
  251.     XIfEvent(dpy, &event, WaitForNotify, (char *) win);
  252.  
  253.    /* 
  254.     * install the colormap windows property so that overlay colormap
  255.     * takes hold when we move cursor into window
  256.     */
  257.     winList[0] = win;
  258.     winList[1] = owin;
  259.     XSetWMColormapWindows(dpy, win, winList, 2);
  260.  
  261.    /*
  262.     * get the 'white' pixel value, we will need this
  263.     * to set colormap index for overlay drawing
  264.     */
  265.     XAllocNamedColor(dpy, ocmap, "white", &spix, &pixel);
  266.     WHITE_PIXEL_NUM = pixel.pixel;
  267.  
  268.    /* 
  269.     * connect the context to the main planes window 
  270.     */
  271.     if (!glXMakeCurrent(dpy, win, cx) == GL_TRUE) {
  272.         return 0;
  273.     }
  274.  
  275.  
  276.    /*
  277.     * get the window size and location so that we can
  278.     * make the cylinder track the mouse movements *somewhat* acurately
  279.     */
  280.  
  281.     XGetWindowAttributes(dpy, win, &winattrs);
  282.     xorigin = winattrs.x;
  283.     yorigin = winattrs.y;
  284.     width = winattrs.width;
  285.     height = winattrs.height;
  286.  
  287.  
  288.    /*
  289.     * all right! finally some OpenGL stuff!!
  290.     * enable zbuffer depth test
  291.     */
  292.     glEnable(GL_DEPTH_TEST);
  293.     glDepthFunc(GL_LEQUAL);
  294.  
  295.    /*
  296.     * set up projection matrix, perspective projection if you please...
  297.     */
  298.     glMatrixMode(GL_PROJECTION);
  299.     glLoadIdentity();
  300.     gluPerspective((double) 450, (double) (width/(float)height), 
  301.                  (double) .25, (double) 15.0);
  302.  
  303.    /*
  304.     * ok, model transformations from now on...
  305.     */
  306.     glMatrixMode(GL_MODELVIEW);
  307.  
  308.    /*
  309.     * set up lighting attributes
  310.     */
  311.     glLightfv(GL_LIGHT1, GL_POSITION, lpos);
  312.     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
  313.     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
  314.     glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
  315.  
  316.  
  317.    /*
  318.     * set up light model attributes
  319.     */
  320.     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  321.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, alm);
  322.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 
  323.  
  324.    /*
  325.     * turn on the light!
  326.     */
  327.     glEnable(GL_LIGHTING);
  328.     glEnable(GL_LIGHT1);
  329.  
  330.  
  331.    /*
  332.     * hit the model matrix with an initial translation, 3 units back in
  333.     * Z direction to add a little spice...
  334.     */
  335.     glTranslatef(0., 0., -3.);
  336.  
  337.  
  338.     /*
  339.      * set X input stuff
  340.      */
  341.      XSelectInput(dpy, win, ExposureMask);
  342.  
  343.      XSelectInput(dpy, win, ExposureMask |StructureNotifyMask |
  344.                                ButtonPressMask | Button1MotionMask |
  345.                    SubstructureNotifyMask | KeyPressMask |
  346.                                KeyReleaseMask | ButtonReleaseMask );
  347.  
  348.     /*
  349.      * do the same for overlay window 
  350.      */
  351.      XSelectInput(dpy, owin, ExposureMask);
  352.      XSelectInput(dpy, owin, ExposureMask |StructureNotifyMask |
  353.                                ButtonPressMask | Button1MotionMask |
  354.                    SubstructureNotifyMask | KeyPressMask |
  355.                                KeyReleaseMask | ButtonReleaseMask );
  356.  
  357.  
  358.  
  359.     /*
  360.      * ready to go, print out instructions to the screen
  361.      */
  362.  
  363.      printf("\npush leftmouse button and drag to move cylinder!\n");
  364.      printf("\n 'o' key to toggle overlay drawing");
  365.      printf("\n 't' key to toggle scene transparency");
  366.      printf("\n 'Esc' key to quit\n");
  367.      fflush(stdout);
  368.  
  369.  
  370.     /*
  371.      * the dreaded X event loop...
  372.      */
  373.      while (1) {         /* loop forever... */
  374.  
  375.             XNextEvent(dpy, &event);
  376.  
  377.             switch (event.type) {
  378.  
  379.         case Expose:
  380.                     if (event.xexpose.count)
  381.                         continue;
  382.                 drawScene();
  383.                     if (!WIRE_FRAME) {   /* have to manually clear overlay */
  384.                                          /* since code is too 'dumb' to    */
  385.                          /* redraw overlay in drawScene    */
  386.                         glXMakeCurrent(dpy, owin, ocx);
  387.                         glClearColor(0.0, 0.0, 0.0, 0.0);
  388.                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  389.                         }
  390.             break;
  391.  
  392.          case ConfigureNotify:
  393.  
  394.                    /*
  395.                     * resize or reposition, so get pertinent window
  396.                     * info and update scene.   don't forget to
  397.                     * resize overlay window!
  398.                     */
  399.  
  400.                     XGetWindowAttributes(dpy, win, &winattrs);
  401.                     xorigin = winattrs.x;
  402.                     yorigin = winattrs.y;
  403.                     width = winattrs.width;
  404.                     height = winattrs.height;
  405.             glXMakeCurrent(dpy, win, cx);
  406.                     glViewport(0, 0, width, height);
  407.                 drawScene();
  408.  
  409.                     XResizeWindow(dpy, owin, width, height);
  410.                     glXMakeCurrent(dpy, owin, ocx);
  411.                     glViewport(0, 0, width, height);
  412.             break;
  413.  
  414.  
  415.         case KeyPress:
  416.  
  417.                     XLookupString((XKeyEvent *) &event, xbuf, nchar, &key, &cs);
  418.  
  419.                     switch (key) {
  420.  
  421.                         case XK_Escape:   /* quit */
  422.                             printf("\n bye...\n");
  423.                             exit(0);
  424.                             break;
  425.  
  426.                         case XK_T:       /* toggle scene transparency */
  427.                         case XK_t:
  428.                             TRANSPARENT = !TRANSPARENT;
  429.                             drawScene();
  430.                             break;
  431.  
  432.                         case XK_O:       /* toggle overlay drawing */
  433.                         case XK_o:
  434.                             WIRE_FRAME = !WIRE_FRAME;
  435.                     drawScene();
  436.                             break;
  437.                         }
  438.  
  439.                     break;
  440.  
  441.  
  442.         case MotionNotify:
  443.                    /*
  444.                     * get cursor position and rotate scene
  445.                     */
  446.                     fx = (float) event.xmotion.x;
  447.                     fy = (float) event.xmotion.y;
  448.                     rx = -500.0 * (2.0*(fy - yorigin)/height-1.0);
  449.             ry = 500.0 * (2.0*(fx - xorigin)/width-1.0);
  450.  
  451.             drawScene();
  452.             break;
  453.  
  454.         default:
  455.             break;
  456.  
  457.                 }
  458.             }
  459.  
  460. }
  461.  
  462.  
  463. /*
  464.  * main scene drawing routine.
  465.  */
  466. void
  467. drawScene()
  468. {
  469.  
  470.     
  471.     if (!WIRE_FRAME) {
  472.        /*
  473.         * no wire frame, so update main planes scene.
  474.         * set the main plane window as the current window to draw into,
  475.         * clear the window and depth buffer
  476.         */
  477.         glXMakeCurrent(dpy, win, cx);
  478.         glClearColor(0.0, 0.0, 0.0, 0.0);
  479.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  480.  
  481.        /*
  482.         * push down a new matrix onto the matrix stack.  then apply
  483.         * a couple of rotations
  484.         */  
  485.         glPushMatrix();
  486.         glRotatef((float) ry, 0., 1., 0.);
  487.         glRotatef((float) -rx, 1., 0., 0.);
  488.     
  489.        /*
  490.         * disable blending and turn on depth check
  491.         */
  492.         glDisable(GL_BLEND);
  493.         glBlendFunc(GL_ONE, GL_ZERO);
  494.         glDepthMask(1);
  495.  
  496.        /*
  497.         * set up materials
  498.         */
  499.         setMaterial(GL_FRONT, ambient2, diffuse2, specular2, shininess);
  500.         setMaterial(GL_BACK, bamat, bdmat, bsmat, shin);
  501.  
  502.        /*
  503.         * scale down cylinder slightly
  504.         */
  505.         glScalef(.5, 1.0, .5);
  506.         drawcyl();
  507.  
  508.        /*
  509.         * pop matrix off of stack
  510.         */
  511.         glPopMatrix();
  512.  
  513.        /*
  514.         * new matrix, apply same rotations
  515.         */
  516.         glPushMatrix();
  517.  
  518.         glRotatef((float) ry, 0., 1., 0.);
  519.         glRotatef((float) -rx, 1., 0., 0.);
  520.  
  521.        /*
  522.         * if transparency enabled, turn off depth check, enable blending
  523.         */
  524.         if (TRANSPARENT) {
  525.             glDepthMask(0);
  526.             glEnable(GL_BLEND);
  527.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  528.             }
  529.         else  {  /* else no transparency */
  530.             glDisable(GL_BLEND);
  531.             glDepthMask(1);
  532.             }
  533.  
  534.        /*
  535.         * set up materials, draw cylinder 
  536.         */
  537.         setMaterial(GL_FRONT, amat, dmat, smat, shin);
  538.         setMaterial(GL_BACK, amat, dmat, smat, shin);
  539.  
  540.         drawcyl();
  541.  
  542.        /*
  543.         * disable blending
  544.         */
  545.         if (TRANSPARENT)
  546.             glDisable(GL_BLEND);
  547.  
  548.  
  549.        /*
  550.         * pop off matrix, swap buffers to show updated scene
  551.         */
  552.         glPopMatrix();
  553.  
  554.         glXSwapBuffers(dpy, win);
  555.         }
  556.  
  557.     else { 
  558.  
  559.        /* 
  560.         * draw into overlay window.  make overlay window current, and
  561.         * clear;
  562.         */
  563.  
  564.         glXMakeCurrent(dpy, owin, ocx);
  565.         glClearColor(0.0, 0.0, 0.0, 0.0);
  566.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  567.  
  568.        /*
  569.         * push down a matrix onto the stack, and apply rotations
  570.         */
  571.         glPushMatrix();
  572.  
  573.         glRotatef((float) ry, 0., 1., 0.);
  574.         glRotatef((float) -rx, 1., 0., 0.);
  575.  
  576.        /*
  577.         * draw the wire box, flush the graphics pipe, pop the matrix off
  578.         * of the matrix stack
  579.         */
  580.         drawBox();
  581.         glFlush();
  582.  
  583.         glPopMatrix();
  584.  
  585.         }
  586. }
  587.  
  588.  
  589. /*
  590.  * routine to draw cylinder.  note that normals are specified with
  591.  * glNormal3fv() to take advantage of lighting.
  592.  */
  593. void
  594. drawcyl()
  595. {
  596. double dy = .2;
  597. double theta, dtheta = 2*M_PI/20;
  598. double x, y, z;
  599. float n[3], v[3];
  600. int i, j;
  601.  
  602.     for (i = 0, y = -1;  i < 10;  i++, y += dy)  {
  603.             glEnable(GL_LIGHTING);
  604.         glBegin(GL_TRIANGLE_STRIP);
  605.         for (j = 0, theta = 0;  j <= 20;  j++, theta += dtheta)  {
  606.             if (j == 20)  theta = 0;
  607.             x = cos(theta);
  608.             z = sin(theta);
  609.             n[0] = x;  n[1] = 0;  n[2] = z;
  610.             glNormal3fv(n);
  611.             v[0] = x;  v[1] = y;  v[2] = z;
  612.             glVertex3fv(v);
  613.             v[1] = y + dy;
  614.             glVertex3fv(v);
  615.         }
  616.         glEnd();
  617.     }
  618. }
  619.  
  620.  
  621. /*
  622.  * convenience function to set material properties
  623.  */
  624. void
  625. setMaterial(GLenum face, float *ambient, float *diffuse, 
  626.                float *specular, float *shininess)
  627. {
  628.         glMaterialfv(face, GL_AMBIENT, ambient);
  629.         glMaterialfv(face, GL_DIFFUSE, diffuse);
  630.         glMaterialfv(face, GL_SPECULAR, specular);
  631.         glMaterialfv(face, GL_SHININESS, shininess);
  632. }
  633.  
  634.  
  635. /*
  636.  * routine to draw the wire box in the overlay window.  notice that
  637.  * we use color index mode, glIndexi() to set colors here even though
  638.  * the main plane window uses RGB
  639.  */
  640. void
  641. drawBox()
  642. {
  643.  
  644.      float v[2];
  645.  
  646.      glIndexi(WHITE_PIXEL_NUM);
  647.  
  648.      glBegin(GL_LINE_LOOP);
  649.          v[0] = v[1] = -.5;
  650.          glVertex2fv(v);
  651.          v[0] = .5;
  652.          glVertex2fv(v);
  653.          v[1] = .5;
  654.          glVertex2fv(v);
  655.          v[0] = -.5;
  656.          glVertex2fv(v);
  657.      glEnd(); 
  658.      
  659.  
  660.  
  661. }
  662.  
  663.  
  664.  
  665.